package org.bangumibuddy.security.config;

import lombok.extern.slf4j.Slf4j;
import org.bangumibuddy.config.property.JwtProperties;
import org.bangumibuddy.config.property.Webproperties;
import org.bangumibuddy.security.filter.JwtAuthenticationFilter;
import org.bangumibuddy.security.handler.CustomAccessDeniedHandler;
import org.bangumibuddy.security.handler.CustomAuthenticationFailureHandler;
import org.bangumibuddy.utils.JwtManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;

@Configuration
@Slf4j
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    AuthenticationProvider authenticationProvider;

    @Autowired
    Webproperties webproperties;

    @Autowired
    JwtProperties jwtProperties;

    AuthenticationManager authenticationManager;

    @Autowired
    AuthenticationConfiguration authenticationConfiguration;

    @Autowired
    @Qualifier("handlerExceptionResolver")
    private HandlerExceptionResolver resolver;

    @Autowired
    JwtManager jwtManager;

    @Autowired
    CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

    @Autowired
    CustomAccessDeniedHandler customAccessDeniedHandler;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {

        log.trace("正在初始化Security组件");

        //设置除了login和静态资源外其他访问都需要授权
        httpSecurity.authorizeHttpRequests(
                request -> {
                   request.requestMatchers("/assets/**").permitAll()
                           .requestMatchers("/user/login").permitAll()
                           .requestMatchers("/socket/**").permitAll()
                           .anyRequest().authenticated();
                });
        authenticationManager = authenticationConfiguration.getAuthenticationManager();
        httpSecurity.sessionManagement(session->
            session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        );

        //添加jwt验证过滤器
        httpSecurity.addFilterBefore(
                new JwtAuthenticationFilter(authenticationConfiguration,jwtProperties,resolver,jwtManager),
                UsernamePasswordAuthenticationFilter.class);

        //关闭跨域检查，
        httpSecurity.csrf(csrf->csrf.disable());
        httpSecurity.authenticationProvider(authenticationProvider);

        //禁用默认登录
        httpSecurity.formLogin(formLogin->formLogin.disable());
        httpSecurity.exceptionHandling(exceptionHandling->exceptionHandling.authenticationEntryPoint(customAuthenticationFailureHandler));
        httpSecurity.exceptionHandling(exceptionHandling->exceptionHandling.accessDeniedHandler(customAccessDeniedHandler));

        log.trace("Security组件初始化完成");
        return httpSecurity.build();
    }
}
